package com.hanxiaozhang.exception;

import java.io.IOException;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

/**
 * 〈一句话功能简述〉<br>
 * 〈UndeclaredThrowableException的异常产生举例〉
 * <p>
 * https://blog.csdn.net/weixin_45701550/article/details/123450727
 *
 * @author hanxinghua
 * @create 2023/3/30
 * @since 1.0.0
 */
public class No1UndeclaredThrowableExceptionExample {

    /*
    查看代理类$Proxy0.class:
    Idea在debug状态下，直接双击shift搜索$Proxy即可找到代理类

     */


    public static void main(String[] args) {

        Class birdClazz = Bird.class;
        Bird bird = new Bird();
        Flyable flyable = (Flyable) Proxy.newProxyInstance(birdClazz.getClassLoader(), birdClazz.getInterfaces(),
                new Handler(bird));

        // 测试没有throws异常，最后抛什么样的异常-> 也是UndeclaredThrowableException
        flyable.fly1();

//        try {
//            flyable.fly();
//        } catch (IOException e) {
//            e.printStackTrace();
//        }
    }


    /**
     * 可飞行接口
     */
    interface Flyable {

        /**
         * 飞行
         *
         * @throws IOException
         */
        void fly() throws IOException;

        void fly1();
    }


    /**
     * 鸟
     */
    static class Bird implements Flyable {

        @Override
        public void fly() throws IOException {

        }

        @Override
        public void fly1() {

        }




    }


    /**
     * 每一个动态代理类的调用处理程序都必须实现InvocationHandler接口
     */
    static class Handler implements InvocationHandler {

        private Object target;

        public Handler(Object target) {
            this.target = target;
        }

        @Override
        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {

//            System.out.println("在真实的对象执行之前我们可以添加自己的操作");
//            Object invoke = method.invoke(target, args);
//            System.out.println("在真实的对象执行之后我们可以添加自己的操作");
//            return invoke;

            System.out.println(String.format("before invoke %s", method.getName()));
            throw new Exception("throw checked exception");
        }
    }

}
